import { isUndefined, isEmpty } from "./checker"
export const toFixed = (num: number, exponent: number) => {
  if (num.toString().indexOf('e') !== -1 || num.toString().indexOf('E') !== -1) {
    // 无限小
    return 0
  }
  let _value = num.toFixed(exponent)
  return Number(_value)
}

export const lowerCase = (s: any) => {
  if (!isUndefined(s)) {
    return (s + '').toLowerCase()
  }
  return ''
}

export const upperCase = (s: any) => {
  if (!isUndefined(s)) {
    return (s + '').toUpperCase()
  }
  return ''
}

export const emtpyToUndefined = <T>(s: T, emptyChecker: (v:T) => boolean = isEmpty): T | undefined => {
  return emptyChecker(s) ? undefined : s
}

export const emtpyToNull = <T>(s: T, emptyChecker: (v:T) => boolean = isEmpty): T | null => {
  return emptyChecker(s) ? null : s
}

export const uuid = () => {
  let s = [], hexDigits = "0123456789abcdef"
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }
  s[14] = "4";
  s[19] = hexDigits.substr((+s[19] & 0x3) | 0x8, 1);
  s[8] = s[13] = s[18] = s[23] = "-";
  let uuid = s.join("");
  return uuid.replace(new RegExp("-", "gm"), "");
}

export const randomNumber = (precision: number, scale: number) => {
  return parseFloat(Math.random().toString().substr(2, precision) + "." + Math.random().toString().substr(2, scale));
}

export const randomInteger = (len: number) => {
  return  parseInt(Math.random().toString().substr(2, len));
}

export const randomString = (len: number) => {
  let arr: string[] = []
  while (arr.length < len) {
    arr = arr.concat(Array.from(Math.random().toString(36).substring(2)))
  }
  return arr.join("").substr(0, len)
}

export const randomBoolean = () => {
  return Math.random() > 0.5 ? true: false;
}

export const pad = (v: string, len: number, padString: string, isStart: boolean = true): string => {
  if (isStart && v.padStart) {
    return v.padStart(len, padString)
  } else if (!isStart && v.padEnd) {
    return v.padEnd(len, padString)
  } else {
    if (v.length >= len) {
      return v
    } else {
      return pad(isStart ? `${padString}${v}` : `${v}${padString}`, len, padString, isStart)
    }
  }
}

interface MonadResult {
  success: boolean,
  data?: any,
  msg?: string
}
interface PromiseMonad {
  (...args: any[]): Promise<MonadResult>
}
export interface PromisePairQueue {
  func: PromiseMonad, 
  params: any[]
}

export const createPromiseQueue = (pairs: PromisePairQueue[]): Promise<MonadResult> => {
  return pairs.reduce((pro: Promise<MonadResult>,  p: PromisePairQueue) => {
    return pro.then((r2: MonadResult) => {
      if (r2.success) {
        return p.func.apply(null, p.params)
      } else {
        throw r2.msg ?? ""
      }
    })
  }, Promise.resolve({success: true}))
}

export const performanceMonitor = (name: string, tsBegin: number, warningThreshold = 1000) => {
  const duration = +new Date() - tsBegin
  if (duration > warningThreshold) {
    console.warn(`==PERFORMANCE_WARNING==[${name}] consumes => ${duration} ms`)
  }
}